/**
 * 
 */
package qy.jalgotrade.optimizer.server;

import java.net.UnknownHostException;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.xmlrpc.XmlRpcException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import qy.jalgotrade.barfeed.BaseBarFeed;
import qy.jalgotrade.optimizer.base.AbstractResultSinc;
import qy.jalgotrade.optimizer.base.OptimizingGoal;
import qy.jalgotrade.optimizer.base.ParameterSource;
import qy.jalgotrade.optimizer.base.Parameters;
import qy.jalgotrade.optimizer.base.ResultSincFactory;
import qy.jalgotrade.optimizer.base.Results;
import qy.jalgotrade.optimizer.xmlrpc.XmlRpcServerRunnable;
import qy.jalgotrade.utils.PySpecs.Iter;

/**
 * @author c-geo
 *
 */
public class RemoteServer {

	public static final String REMOTE_SERVER = "RemoteServer";

	private static Logger logger = LoggerFactory.getLogger(RemoteServer.class);

	/**
	 * 
	 * @param barFeed            The bar feed that each worker will use to backtest the strategy.
	 * @param strategyParameters he set of parameters to use for backtesting. An iterable object where
	 *                           **each element is a tuple that holds parameter values**.
	 *                           strategyParameters: 回测使用的 参数集. 需为 iterable, 每次迭代返回一个 参数组 tuple.
	 * @param goal
	 * @param address            The address to listen for incoming worker connections.
	 * @param port               The port to listen for incoming worker connections.
	 * @return
	 * @throws XmlRpcException
	 * @throws UnknownHostException
	 */
	public static Results run(BaseBarFeed barFeed, Iter<Parameters> strategyParameters, OptimizingGoal goal,
	        String address, int port) throws UnknownHostException, XmlRpcException {

		return run(barFeed, strategyParameters, goal, address, port, 200);
	}

	/**
	 * Executes a server that will provide bars and strategy parameters for workers to use.
	 * 
	 * @param barFeed            The bar feed that each worker will use to backtest the strategy.
	 * @param strategyParameters he set of parameters to use for backtesting. An iterable object where
	 *                           **each element is a tuple that holds parameter values**.
	 *                           strategyParameters: 回测使用的 参数集. 需为 iterable, 每次迭代返回一个 参数组 tuple.
	 * @param goal
	 * @param address            The address to listen for incoming worker connections.
	 * @param port               The port to listen for incoming worker connections.
	 * @param batchSize          The number of strategy executions that are delivered to each worker.
	 * @return
	 * @throws XmlRpcException
	 * @throws UnknownHostException
	 */
	public static Results run(BaseBarFeed barFeed, Iter<Parameters> strategyParameters, OptimizingGoal goal,
	        String address, int port, int batchSize) throws UnknownHostException, XmlRpcException {

		ParameterSource paramSource = new ParameterSource(strategyParameters);
		AbstractResultSinc resultSinc = ResultSincFactory.create(goal);
		XmlRpcServerRunnable xrsr = new XmlRpcServerRunnable(paramSource, resultSinc, barFeed, address, port, goal,
		        batchSize);
		Thread serverThread = new Thread(xrsr, REMOTE_SERVER);

		logger.info("Starting server");

		serverThread.start();
		try {
			serverThread.join();
		} catch (InterruptedException e) {
			logger.error("InterruptedException: {} (stack trace: {})", e, ExceptionUtils.getStackTrace(e));
		}

		logger.info("Server finished");

		Results ret = resultSinc.getBest();
		if (ret != null) {
			logger.info("Best final result: {}, with parameters: {}", ret, ret.getParameters());
		} else {
			logger.error("No results. All jobs failed or no jobs were processed.");
		}

		return ret;
	}

	/**
	 * 
	 */
	private RemoteServer() {

	}
}
